﻿using Castle.DynamicProxy;
using SBlogCore.Common.CacheExtend;
using SBlogCore.Common.CacheExtend.Attributes;
using System.Reflection;
using System.Text;

namespace SBlogCore.Common.AutofacExtend.Aops
{
    public class SBlogCacheAop : IInterceptor
    {
        private readonly ISBlogCoreCache _memoryCache;

        public SBlogCacheAop(ISBlogCoreCache redisCache)
        {
            this._memoryCache = redisCache;
        }
        /// <summary>
        /// 实例化IInterceptor唯一方法 
        /// </summary>
        /// <param name="invocation"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void Intercept(IInvocation invocation)
        {
            var method = invocation.Method;
            ServiceAopCacheAttribute? redisCacheAttribute = method.GetCustomAttributes<ServiceAopCacheAttribute>().FirstOrDefault();
            //只有添加ServiceRedisCacheAttribute特性的才会被缓存
            if (redisCacheAttribute != null)
            {
                //获取缓存的Key
                var key = GetCacheKey(invocation,redisCacheAttribute.KeyName ?? string.Empty);
                //查询缓存
                var cache = _memoryCache.Get<object>(key);
                if (cache != null)
                {
                    invocation.ReturnValue = cache;
                    return;
                }
                invocation.Proceed();
                var result = invocation.ReturnValue;
                _memoryCache.Create(key, result, redisCacheAttribute.OutTime);
            }
            else {
                invocation.Proceed();
            }
        }

        /// <summary>
        /// 组装key
        /// </summary>
        /// <param name="invocation"></param>
        /// <param name="key"></param>
        /// <returns>HelloDemoAop_Task=age|Int32:1;name|String:xm;ok|Boolean:True;</returns>
        private static string GetCacheKey(IInvocation invocation,string key="")
        {
            
            var method = invocation.Method;
            if (method != null&&string.IsNullOrEmpty(key))
            {
                var arguments = invocation.Arguments;
                if (string.IsNullOrEmpty(key))
                {
                    StringBuilder builder = new StringBuilder();

                    for (int i = 0; i < arguments.Length; i++)
                    {
                        builder.Append($"{arguments[i]}:");
                    }
                    key = $"{method.Name}={builder}";
                }
            }
            return key;
        }

    }
}
